package com.github.cooingandwooing.common.core.config;

import com.github.cooingandwooing.common.core.model.ResponseBean;

import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.lang.Nullable;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/**
 * 〈统一响应〉 待处理（一般不用这个方法 ）
 *
 * @author Administrator
 * @create 2022/4/27
 * @since 1.0.0
 */
@RestControllerAdvice
public class ResponseBody2ResponseAdvice implements ResponseBodyAdvice<Object> {


    /**
     * ResponseBodyAdvice 接口是在 Controller 执行 return 之后，在 response 返回给客户端之前，执行的对 response 的一些处理，可以实现对 response 数据的一些统一封装或者加密等操作。
     * 该接口一共有两个方法：
     * （1）supports —— 判断是否要执行beforeBodyWrite方法，true为执行，false不执行 —— 通过supports方法，我们可以选择哪些类或哪些方法要对response进行处理，其余的则不处理。
     * （2）beforeBodyWrite —— 对 response 处理的具体执行方法。
     * note： String 类型使用 StringHttpMessageCoverter 序列化，不会走我们定义的这个 ResponseBodyAdvice 中
     */
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        // 只处理 AbstractJackson2HttpMessageConverter 类型，注意使用默认的 jackson （序列化）
        // Jackson 是当前用的比较广泛的，用来序列化和反序列化 json 的 Java 的开源框架。Jackson 社 区相对比较活跃，更新速度也比较快， 从 Github 中的统计来看，Jackson 是最流行的 json 解析器之一 。
        // Spring MVC 的默认 json 解析器便是 Jackson。
        return AbstractJackson2HttpMessageConverter.class.isAssignableFrom(converterType)
                && (!returnType.getMethod().getReturnType().isAssignableFrom(ResponseBean.class))
                // 忽略 ResponseEntity
                && (!returnType.getMethod().getReturnType().isAssignableFrom(ResponseEntity.class));
    }

    @Override
    @Nullable
    public Object beforeBodyWrite(@Nullable Object body, MethodParameter returnType, MediaType selectedContentType,
            Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        return ResponseBean.seccess(body);
    }
}
